package com.jzwl.common.upload;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.Vector;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.google.common.base.Splitter;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class SftpChannel {

	private static Logger log = Logger.getLogger(SftpChannel.class);
	public static String TAB_SPLIT = "|";

	ChannelSftp sftp = null;

	//账号

	private static String username = "root";

	//主机ip

	private static String host = "112.125.90.162";

	//密码

	private static String password = "NCgfkj2018";

	//端口

	private static int port = 22;

	public SftpChannel() throws Exception {
		try {
			JSch jsch = new JSch();
			jsch.getSession(username, host, port);
			Session sshSession = jsch.getSession(username, host, port);
			log.info("Session created!");
			sshSession.setPassword(password);
			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");
			// sshConfig.put("userauth.gssapi-with-mic", "no");
			sshSession.setConfig(sshConfig);
			sshSession.connect();
			log.info("Session connected!");
			log.info("Opening Channel!");
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			sftp = (ChannelSftp) channel;
			log.info("Connected to " + host + "!!");
			log.info("登录成功!!!");
		} catch (Exception e) {
			log.info("连接sftp失败!");
			log.error(e.getMessage(), e);
			throw new Exception("连接sftp失败!" + e.getMessage());
		}
	}

	public void batchUpload(String directory, String uploadFile) throws Exception {
		File file = new File(uploadFile);
		LinkedList<File> fList = new LinkedList<File>();
		fList.addLast(file);
		String str = null;
		while (fList.size() > 0) {
			File f = fList.removeFirst();
			for (File file2 : f.listFiles()) {
				if (file2.isFile()) {// 文件
					log.info(file2);
					str = file2.toString().replace("\\", "\\\\");
					upload(directory, str);
				}
			}
		}

	}

	/**
	 * 删除文件
	 * @param directory 要删除文件所在目录
	 * @param deleteFile  要删除的文件
	 */
	public void delete(String directory, String deleteFile) throws Exception {
		Vector fileList = sftp.ls(directory);
		Iterator it = fileList.iterator();
		while (it.hasNext()) {
			String fileName = ((LsEntry) it.next()).getFilename();
			if (deleteFile.equals(fileName)) {
				sftp.cd(directory);
				sftp.rm(deleteFile);
			}
		}
	}

	/**
	 * 下载文件
	 * @param directory 下载目录
	 * @param downloadFile 下载的文件
	 * @param saveFile 存在本地的路径
	 */
	public File download(String directory, String downloadFile, String saveFile) throws Exception {
		sftp.cd(directory);
		File file = new File(saveFile);
		sftp.get(downloadFile, new FileOutputStream(file));
		return file;
	}

	/**
	 * 列出目录下的全部文件
	 */
	@SuppressWarnings("rawtypes")
	public List<String> listFiles(String directory) throws Exception {
		Vector fileList;
		List<String> fileNameList = new ArrayList<String>();

		fileList = sftp.ls(directory);
		Iterator it = fileList.iterator();
		while (it.hasNext()) {
			String fileName = ((LsEntry) it.next()).getFilename();
			if (".".equals(fileName) || "..".equals(fileName)) {
				continue;
			}
			fileNameList.add(fileName);
		}
		return fileNameList;
	}

	/**
	 * 重命名文件
	 * @param directory 要重命名文件所在目录
	 * @param oldName 要重命名的文件
	 * @param newName 新文件名
	 */
	@SuppressWarnings("rawtypes")
	public boolean rename(String directory, String oldName, String newName) throws Exception {
		Vector fileList = sftp.ls(directory);
		Iterator it = fileList.iterator();
		while (it.hasNext()) {
			String fileName = ((LsEntry) it.next()).getFilename();
			if (oldName.equals(fileName)) {
				sftp.cd(directory);
				sftp.rename(oldName, newName);
				return true;
			}
		}
		return false;
	}

	public void upload(String directory, File file) throws Exception {
		FileInputStream e = new FileInputStream(file);
		sftp.cd(directory);
		sftp.put(e, file.getName());
	}

	public String upload(InputStream file, String fileName) throws Exception {
		try {
			List<String> result = Splitter.on(".").trimResults().splitToList(fileName);
			fileName = UUID.randomUUID().toString() + "." + result.get(1);
			sftp.cd("/www/wwwroot/NCgeifet");
			sftp.put(file, fileName);
			return "http://112.125.90.162:888/" + fileName;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			close();
		}
		return null;
	}

	public void cd(String directory) throws Exception {
		sftp.cd(directory);
	}

	public void mkdir(String directory) throws Exception {
		sftp.mkdir(directory);
	}

	/**
	 * 上传文件
	 * @param directory 上传的目录
	 * @param uploadFile  要上传的文件
	 * @throws Exception 
	 */
	public void upload(String directory, String uploadFile) throws Exception {
		upload(directory, new File(uploadFile));
	}

	/**
	 * 关闭通道
	 * @throws Exception
	 */
	public void close() {
		try {
			if (sftp != null) {
				if (sftp != null && sftp.isConnected()) {
					sftp.disconnect();
				}
				if (sftp.getSession() != null && sftp.getSession().isConnected()) {
					sftp.getSession().disconnect();
				}
			}
		} catch (Exception e) {
			log.error("关闭SFTP通道异常：" + e.getMessage());
		}
	}

	public boolean checkFileExist(String directory, String downloadFile) throws Exception {
		sftp.cd(directory);
		InputStream input = sftp.get(downloadFile);
		if (input == null) {
			return false;
		} else {
			return true;
		}
	}

	public <T> List<T> downloadFileToListObj(String directory, String downloadFile, Class<T> clazz) throws Exception {
		if (!checkFileExist(directory, downloadFile)) {
			log.error("文件[" + downloadFile + "]不存在！");
			return null;
		}
		File file = download(directory, downloadFile, downloadFile);
		List<T> list = new ArrayList<T>();
		List<String> lines = FileUtils.readLines(file, "UTF-8");

		Method m = clazz.getDeclaredMethod("sortProperties");
		String sortProperties = (String) m.invoke(clazz.newInstance());
		if (StringUtils.isBlank(sortProperties)) {
			throw new Exception(clazz.getName() + " 的sortProperties方法返回值为空或者方法不存在!");
		}

		for (int i = 0; i < lines.size(); i++) {
			String line = lines.get(i);
			line = line.trim();
			if (line.indexOf("|") < 0) {//第一行可能是条数不能直接解析 add by djh
				continue;
			}
			if (StringUtils.isBlank(line)) {
				continue;
			}
			//			if (0 == i) {
			//				String fistLine = file.getName() + "|" + (lines.size() - 2);
			//				if (line != null && !line.equals(fistLine)) {
			//					throw new Exception("文件：【" + file.getName() + "】第一行头解析错误！");
			//				}
			//			}
			//			if (i > 1) {
			T o = getLineObject(clazz, line, sortProperties.split(","));
			list.add(o);
			//			}
		}
		deleteFile(file.getAbsolutePath());
		return list;
	}

	public <T> T getLineObject(Class<T> zlass, String line, String[] filedsArray) throws Exception {
		Object obj = zlass.newInstance();
		String[] values = line.split("\\|");
		for (int i = 0; i < filedsArray.length; i++) {
			String fieldName = filedsArray[i];
			String value = values[i];
			bindFieldValue(obj, fieldName, value);
		}
		return (T) obj;
	}

	public static void bindFieldValue(Object obj, String fieldName, String fieldValue) throws Exception {
		String method = getMethodName(fieldName);
		Method getMethod = obj.getClass().getMethod("get" + method, new Class[] {});
		Class zlass = getMethod.getReturnType();
		Method setMethod = obj.getClass().getMethod("set" + method, new Class[] { zlass });
		if (zlass == String.class) {
			setMethod.invoke(obj, new Object[] { fieldValue });
			return;
		} else if (zlass == Integer.class || zlass == Float.class || zlass == Long.class || zlass == Double.class
				|| zlass == Byte.class || zlass == Boolean.class || zlass == Character.class
				|| zlass == java.sql.Timestamp.class) {
			Method valueOf = zlass.getMethod("valueOf", new Class[] { String.class });
			Object valueObj = valueOf.invoke(zlass, new Object[] { fieldValue });
			setMethod.invoke(obj, new Object[] { valueObj });
		} else if (zlass == BigDecimal.class) {

			setMethod.invoke(obj, new Object[] { new BigDecimal(fieldValue) });
		} else if (zlass == java.util.Date.class || zlass == java.sql.Date.class) {
			Object dateObj = zlass.newInstance();
			setMethod.invoke(obj, new Object[] { dateObj });
		} else {
			log.error("未处理的数据类型:" + zlass);
			throw new Exception("未处理的数据类型:" + zlass);
		}
	}

	private static String getMethodName(String objName) {
		String funName = objName.substring(0, 1).toUpperCase();
		if (objName.length() > 1) {
			funName += objName.substring(1, objName.length());
		}
		return funName;
	}

	public static boolean deleteFile(String filePath) {
		boolean flag;
		File file = new File(filePath);
		if (file.isFile() && file.exists()) {
			file.delete();
			flag = true;
		} else {
			log.error("目标文件不存在！该目录为：" + filePath);
			flag = false;
		}
		return flag;
	}

	public ChannelSftp getSftp() {
		return sftp;
	}

	public void setSftp(ChannelSftp sftp) {
		this.sftp = sftp;
	}

	public static void main(String[] args) {
		String str = "192.168.0.1";
		String[] strarray = str.split(".");
		List<String> result = Splitter.on(".").trimResults().splitToList(str);
		System.out.println(result.get(0));
	}
}